package ru.ifmo.swing.genetics.config.operator;

import org.uncommons.watchmaker.framework.EvolutionaryOperator;
import org.uncommons.watchmaker.framework.operators.EvolutionPipeline;
import ru.ifmo.swing.EvolutionControlWithConfigProvider;
import ru.ifmo.swing.genetics.config.common.ChooserListener;
import ru.ifmo.swing.genetics.config.common.MultiChooser;

import javax.swing.*;
import java.util.*;

/**
 * @author avhaliullin
 */
public class EvolutionOperatorsChooser<T> implements EvolutionControlWithConfigProvider, EvolutionaryOperator<T> {
    private final MultiChooser<EvolutionaryOperator<T>> control;
    private EvolutionaryOperator<T> operator;

    public EvolutionOperatorsChooser(Map<String, EvolutionaryOperator<T>> operators) {
        control = new MultiChooser<EvolutionaryOperator<T>>(operators);
        control.addListener(new ChooserListener<List<EvolutionaryOperator<T>>>() {
            public void chosen(List<EvolutionaryOperator<T>> operators) {
                List<EvolutionaryOperator<T>> op = new ArrayList<EvolutionaryOperator<T>>(operators);
                op.add(new TrivialOperator());
                operator = new EvolutionPipeline<T>(op);
            }
        });
    }


    public JComponent getControl() {
        return control;
    }

    public void reset() {
    }

    public void setDescription(String description) {
        control.setTitle(description);
    }

    public List<T> apply(List<T> selectedCandidates, Random rng) {
        return operator.apply(selectedCandidates, rng);
    }

    public Map<String, Object> getParamValues() {
        Map<String, Object> res = new TreeMap<String, Object>();
        List items = control.getItems();
        int index = 0;
        for (Object item : items) {
            res.put("Selected operator #" + index++, item);
        }
        return res;
    }

    // To trick EvolutionPipeline
    class TrivialOperator implements EvolutionaryOperator<T> {

        public List<T> apply(List<T> selectedCandidates, Random rng) {
            return selectedCandidates;
        }
    }
}
